import { Graph, Shape, Addon } from '@antv/x6'
import insertCss from 'insert-css'
import { Basecoat } from '@antv/x6/es/common'
import { customRect } from '@/components/FlowEdit/shape'



// 业务数据转为节点
function formatePortData(row) {
  // return data?.map(row => {
  const { portName } = row
  return {
    shape: 'custom-rect',
    type: 'interface',
    label: portName,
    data: row
  }
  // })
}

// 判断节点是否可以拖拽
function disabledNode(graph, stencil) {
  // 获取画布的所有节点
  const graphNodes = graph.getNodes()
  // 物料区组二的所有节点
  const stencilNodes = stencil.graphs.group2.getNodes()
  // const nodes = graph.getNodes()
  // 获取物料区所有svg
  // const container = stencil.container
  // console.log(graphNodes, stencilNodes, '===stencil==')
  // 获取画布所有节点的id
  const graphIds = graphNodes.map(item => item?.store?.data?.data?.id)
  stencilNodes.forEach(item => {
    const stencilNodeItem = item?.store?.data?.data.id
    if (graphIds.includes(stencilNodeItem)) {
      // arr.push(item)
      item.setAttrs({
        body: {
          fill: '#ecf5ff',
          stroke: '#d9ecff'
        },
        label: {
          fill: '#8cc5ff',
        },
      })
    } else {
      item.setAttrs({
        body: {
          stroke: '#a3d3ff',
          fill: '#e8f4ff'
        },
        label: {
          fill: '#1890ff',
        },
      })
    }
  })

}

export default class FlowGraph extends Basecoat {
  constructor(optionsData) {
    super()
    this.initData()
    const { graphData = null, stencilData = null } = optionsData
    this.insertCssInit()
    this.graphInit()
    this.stencilInit()
    this.registerNode()
    this.addPageNodeInit()
    // this.createNodeStencil(stencilData)
    // this.addNodeGraph()
    // this.eventCollection(isDisabledBtn)
    // if (graphData) {
    // console.log(graphData, '-----graphData--')
    graphData && this.graphRender(graphData)
    // }
    this.graphResize()
    this.stencilResize()
    window.addEventListener('resize', () => {
      this.graphResize()
      this.stencilResize()
    })
    this.graph.on('node:added', ({ node }) => {
      disabledNode(this.graph, this.stencil)
      if (node.store.data.type === 'interface') {
        // 新增节点需要校验是否重复
        const allNodes = this.graph.getNodes()
        const nodeId = node.store?.data?.data?.id
        const sameIds = allNodes.filter(item => item.store?.data?.data?.id === nodeId)
        if (sameIds?.length > 1) {
          // 是重复节点
          this.graph.removeNode(node)
        }
      }
    })
    this?.graph?.on('node:removed', e => {
      disabledNode(this.graph, this.stencil)
    })
  }
  initData() {
    this.graph = null
    this.stencil = null
    this.graphData = null
  }
  graphResize() {
    // 画布动态计算宽高
    const height = document.querySelector('.right').clientHeight
    const width = document.querySelector('.right').clientWidth
    this.graph.resize(width, height - 40)

  }
  stencilResize() {
    // 动态计算物料区的宽高
    const height = document.querySelector('.right').clientHeight
    this.stencil.resizeGroup('group1', { width: 200, height: 100 })
    this.stencil.resizeGroup('group2', { width: 200, height: height - 180 })
  }
  // 初始化画布
  graphInit() {
    this.graph = new Graph({
      container: document.getElementById('graph'),
      grid: {
        visible: true,
        type: 'mesh'
      },
      // 复制粘贴
      clipboard: {
        enabled: true,
        useLocalStorage: false
      },
      // 撤回重做
      history: {
        enabled: true,
        beforeAddCommand(event, args) {
          // console.log(event, args)
          return (JSON.stringify(args.options) !== '{}' && !args?.options?.unset) || event === 'cell:removed'
        }
      },
      scroller: {
        enabled: true,
        pageVisible: true,
        pageBreak: true,
        pannable: true,
        modifiers: 'alt'
      },
      minimap: {
        enabled: true,
        container: document.getElementById('minMap'),
        width: 200,
        height: 150,
        scalable: false
      },
      mousewheel: {
        enabled: true,
        zoomAtMousePosition: true,
        modifiers: 'ctrl',
        minScale: 0.5,
        maxScale: 3
      },
      // 连线
      connecting: {
        allowLoop: false,
        router: {
          name: 'manhattan',
          args: {
            padding: 10
          }
        },
        connector: {
          name: 'rounded',
          args: {
            radius: 2
          }
        },
        highlight: true,
        anchor: 'center',
        connectionPoint: 'anchor',
        allowBlank: false,
        allowMulti: true, //是否允许在相同的起始节点和终止之间创建多条边
        snap: {
          radius: 20
        },
        createEdge() {
          return new Shape.Edge({
            attrs: {
              line: {
                stroke: '#A2B1C3',
                strokeWidth: 2,
                targetMarker: {
                  name: 'block',
                  width: 12,
                  height: 8
                }
              }
            },
            zIndex: 0
          })
        },
        /**
         * 1、不允许页面->页面
         * 2、同一个页面->接口只能有一个
         * 
         */
        validateConnection(e) {
          const { sourceCell, targetCell, targetMagnet, targetView } = e
          const sourceNodeType = sourceCell?.store?.data?.type
          const targetNodeType = targetCell?.store?.data?.type
          // 以当前起点的连线集合,小于2时证明没有连线
          const getTargetNodes = this.model.getOutgoingEdges(sourceCell)
          // 节点是page时，需要判断该节点是否有其他连线
          if (sourceNodeType === 'start') {
            // 起始点只能连接页面interface
            if (targetNodeType === 'page' && getTargetNodes.length < 2) {
              return !!targetMagnet
            }
          } else if (sourceNodeType === 'page') {
            // page只能连接接口
            if (targetNodeType === 'interface' && getTargetNodes.length < 2) {
              return !!targetMagnet
            }
          } else {
            // 节点是interface接口，只能连接page和接口,且不能重复连接
            // 获取当前节点的终止节点id
            // console.log(getTargetNodes, '===getTargetNodes==')
            if (targetNodeType !== 'start') {
              if (getTargetNodes.length > 1) {
                // 删除没有targetid的节点
                const getEdges = getTargetNodes.filter(item => item.store.data?.target?.cell)
                // 获取终止节点的集合
                const getTargetIds = getEdges.map(item => item.store.data?.target?.cell)
                // console.log(getTargetIds, targetCell, '===getTargetIds==')
                if (!getTargetIds.includes(targetCell.store.data.id)) {
                  return !!targetMagnet
                }
              } else {
                return !!targetMagnet
              }
              // const targetNodeIds = getTargetNodes?.pop()?.map(item => item.store.data.target.cell)
              // console.log(targetNodeIds, '===targetNodeIds==')

            }
          }
        }
        // validateConnection({ targetMagnet }) {
        //   return !!targetMagnet
        // }
      },
      highlighting: {
        magnetAvailable: {
          name: 'stroke',
          args: {
            attrs: {
              'stroke-width': 2,
              // fill: '#5F95FF',
              stroke: '#5F95FF'
            }
          }
        },
        magnetAdsorbed: {
          name: 'stroke',
          args: {
            attrs: {
              'stroke-width': 2,
              fill: '#5F95FF',
              stroke: '#5F95FF'
            }
          }
        }
      },
      selecting: {
        enabled: true,
        // 开始投保节点不能选中
        filter(node) {
          return node.store.data.type !== 'start'
        },
        rubberband: true,
        multiple: true,
        movable: false,
        showNodeSelectionBox: true,
        showEdgeSelectionBox: true
      },
      snapline: true,
      keyboard: true,
      clipboard: true
    })
  }
  // 初始化 stencil
  stencilInit() {
    this.stencil = new Addon.Stencil({
      // title: '流程图',
      target: this.graph,
      resizeToFit: true,
      stencilGraphWidth: 200,
      stencilGraphHeight: 280,
      // collapsable: true,
      groups: [
        {
          title: '页面',
          name: 'group1'
        },
        {
          title: '接口',
          name: 'group2'
        }
      ],
      layoutOptions: {
        columns: 2,
        resizeToFit: true
      }
    })
    document.getElementById('stencil').appendChild(this.stencil.container)

    // console.log(this.stencil.onDragStart, '===this.stencil.onDragStart==')
  }
  // 注册节点
  registerNode() {
    Graph.registerNode(
      'custom-rect',
      customRect,
      true
    )
  }
  // 页面初始化创建页面根节点
  addPageNodeInit() {
    // console.log(this.graph.addNode, '==this.graph.addNode==')
    this.graph.addNode({
      shape: 'custom-rect',
      x: 250,
      y: 50,
      type: 'start',
      label: '开始投保',
      attrs: {
        body: {
          fill: '#fff8e6', // 背景颜色
          stroke: '#ffe399' // 边框颜色
        },
        label: {
          fill: '#ffba00'   // 颜色
        }
      }
    })
  }
  // 新建物料区节点
  createNodeStencil(data) {

    // 页面
    const n1 = this.graph.createNode({
      shape: 'custom-rect',
      type: 'page',
      label: '页面',
      attrs: {
        body: {
          fill: '#e7faf0', // 背景颜色
          stroke: '#d0f5e0' // 边框颜色
        },
        label: {
          fill: '#71e2a3'   // 颜色
        }
      }
    })
    // 接口
    const nodes = data?.map(item => {
      const node = formatePortData(item)
      return this.graph?.createNode(node)
    })
    // console.log(nodes, '==nodes==')
    this.stencil.load([n1], 'group1')
    nodes?.length > 0 && this.stencil.load(nodes, 'group2')
    disabledNode(this.graph, this.stencil)
    // this.stencil.container.addEventListener('click', (node) => {
    //   console.log(e, '===e===')
    // })
    // console.log(this.stencil.container, '===this.stencil===')
    // console.log(this.stencil.listeners['cell:mousedown'], '===this.stencil.listeners==')
  }
  // 样式设置
  insertCssInit() {
    insertCss(`
      .right {
        width: calc(100% - 200px);
      }
      #stencil {
        width: 200px;
        position: relative;
        left: 0;
        border-right: 1px solid #dfe3e8;
      }
      #graph {
        width: 100%;
        height: calc(100% - 40px);
        position: relative;
      }
      #minMap {
        position: fixed;
        bottom: 50px;
        right: 80px;
      }
      .x6-widget-stencil {
        background-color: #fff;
      }
      .x6-widget-stencil-title {
        background-color: #fff;
      }
      .x6-widget-stencil-group-title {
        background-color: #fff !important;
      }
      .x6-widget-transform {
        margin: -1px 0 0 -1px;
        padding: 0px;
        border: 1px solid #239edd;
      }
      .x6-widget-transform > div {
        border: 1px solid #239edd;
      }
      .x6-widget-transform > div:hover {
        background-color: #3dafe4;
      }
      .x6-widget-transform-active-handle {
        background-color: #3dafe4;
      }
      .x6-widget-transform-resize {
        border-radius: 0;
      }
      .x6-widget-selection-inner {
        border: 1px solid #239edd;
      }
      .x6-widget-selection-box {
        border: 1px dashed #7c68fc;
        background: rgba(146, 84, 222, .2);
      }
    `)
  }
  // 物料区自适应
  stencilResize() {
    // 动态计算物料区的宽高
    const height = document.querySelector('.right').clientHeight
    this.stencil.resizeGroup('group1', { width: 200, height: 100 })
    this.stencil.resizeGroup('group2', { width: 200, height: height - 180 })
  }
  // 画布自适应
  graphResize() {
    // 画布动态计算宽高
    const height = document.querySelector('.right').clientHeight
    const width = document.querySelector('.right').clientWidth
    this.graph.resize(width, height - 40)

  }
  // 渲染流程图数据
  graphRender(graphData) {
    this.graph.fromJSON(graphData)
  }
}